/**
 * Zod 配置模式定义
 * 该文件定义了所有配置项的模式、类型、默认值和验证规则
 */

import z from 'zod';

declare module 'zod' {
  interface GlobalMeta {
    /**
     * 是否敏感信息，如数据库密码、密钥等
     */
    sensitive?: boolean;
    /**
     * 配置分组标签
     */
    tag?: string;
  }
}

/**
 * 获取环境变量解析使用的布尔值 Schema
 * @returns {z.ZodType<boolean>} Zod Boolean Schema
 */
function booleanSchema(): z.ZodType<boolean> {
  return z.union([z.literal('true'), z.literal('false'), z.boolean()]).transform(val => {
    if (typeof val === 'string') {
      return val === 'true';
    }
    return val;
  });
}

/**
 * 用于预处理环境变量，将字符串转换为数组
 */
const arrayPreprocessSchema = z.string().transform(val => {
  return val.length > 0 ? val.split(',') : [];
});

/**
 * 获取环境变量解析使用的数组 Schema
 * @returns {z.ZodType<Array<?>>} Zod Array Schema
 */
function arraySchema<T>(itemSchema: z.ZodType<T>): z.ZodType<Array<T>> {
  return z.preprocess(val => arrayPreprocessSchema.parse(val), z.array(itemSchema));
}

// 应用配置模式
export const ConfigSchema = z.object({
  // 通用配置项
  NODE_ENV: z
    .enum(['development', 'production', 'test'])
    .default('development')
    .describe('JS 运行时环境')
    .meta({ tag: '通用配置' }),

  // 应用基本信息
  APP_NAME: z.string().default('ElysiaJS Demo').describe('应用程序名称').meta({ tag: '应用信息' }),
  APP_VERSION: z.string().default('1.0.0').describe('应用程序版本号').meta({ tag: '应用信息' }),
  APP_DESCRIPTION: z
    .string()
    .default('A modern web API built with Bun and ElysiaJS')
    .describe('应用程序描述')
    .meta({ tag: '应用信息' }),

  // 服务器配置
  LISTEN_PORT: z.coerce
    .number()
    .int()
    .min(1)
    .max(65535)
    .default(3000)
    .describe('监听端口')
    .meta({ tag: '服务器配置' }),
  LISTEN_HOST: z
    .hostname()
    .default('0.0.0.0')
    .describe('监听的主机地址')
    .meta({ tag: '服务器配置' }),
  ADVERTISE_PORT: z.coerce
    .number()
    .int()
    .min(1)
    .max(65535)
    .default(3000)
    .describe('访问端口')
    .meta({ tag: '服务器配置' }),
  ADVERTISE_HOST: z
    .hostname()
    .default('127.0.0.1')
    .describe('访问主机地址')
    .meta({ tag: '服务器配置' }),

  // 数据库配置
  DATABASE_URL: z
    .url()
    .default('postgres://postgres:123456789@127.0.0.1:5432/elysia_demo')
    .describe('数据库URL')
    .meta({ sensitive: true, tag: '数据库配置' }),

  // 日志配置
  LOG_LEVEL: z
    .enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'])
    .default('info')
    .describe('日志级别')
    .meta({ tag: '日志配置' }),
  LOG_FILE_PATH: z
    .string()
    .default('')
    .describe('日志输出文件路径，置空则不输出到文件')
    .meta({ tag: '日志配置' }),

  // Openapi 配置
  OPENAPI_ENABLED: booleanSchema()
    .default(true)
    .describe('是否启用 OpenAPI 接口')
    .meta({ tag: 'OpenAPI配置' }),
  OPENAPI_PATH: z
    .string()
    .default('/openapi')
    .describe('OpenAPI 接口访问路径')
    .meta({ tag: 'OpenAPI配置' }),

  // OpenTelemetry 配置
  OTEL_ENABLED: booleanSchema()
    .default(false)
    .describe('是否启用 OpenTelemetry')
    .meta({ tag: 'OpenTelemetry配置' }),

  // Cors 配置
  CORS_ORIGIN: z
    .union([
      booleanSchema(),
      z.literal('*'),
      arraySchema(
        z.string().transform(val => {
          try {
            return new RegExp(val);
          } catch {
            return val;
          }
        })
      ),
    ])
    .prefault('*')
    .describe('CORS 允许的源')
    .meta({ tag: 'CORS配置' }),
  CORS_METHODS: z
    .union([
      booleanSchema(),
      z.literal('null').transform(() => null),
      z.literal('undefined').transform(() => undefined),
      z.literal(''),
      z.literal('*'),
      arraySchema(z.string()),
    ])
    .prefault('*')
    .describe('CORS 允许的方法')
    .meta({ tag: 'CORS配置' }),
  CORS_ALLOWED_HEADERS: z
    .union([
      z.literal('true').transform(() => true as const),
      z.literal('*'),
      arraySchema(z.string()),
    ])
    .prefault('*')
    .describe('CORS 允许的请求头')
    .meta({ tag: 'CORS配置' }),
  CORS_EXPOSE_HEADERS: z
    .union([
      z.literal('true').transform(() => true as const),
      z.literal('*'),
      arraySchema(z.string()),
    ])
    .prefault('*')
    .describe('CORS 暴露的请求头')
    .meta({ tag: 'CORS配置' }),
  CORS_CREDENTIALS: booleanSchema()
    .default(true)
    .describe('CORS 是否允许携带 Cookie')
    .meta({ tag: 'CORS配置' }),
  CORS_MAX_AGE: z.coerce.number().default(5).describe('CORS 缓存时间').meta({ tag: 'CORS配置' }),
  CORS_PREFLIGHT: booleanSchema()
    .default(true)
    .describe('CORS 是否允许预检请求')
    .meta({ tag: 'CORS配置' }),
});

export type Config = z.infer<typeof ConfigSchema>;
